/*
Copyright 2018-2024 New Vector Ltd.
Copyright 2017 Vector Creations Ltd
Copyright 2015 OpenMarket Ltd

SPDX-License-Identifier: AGPL-3.0-only
Please see LICENSE in the repository root for full details.
 */

#import "MXKAccountDetailsViewController.h"

@import MatrixSDK;
#import "MXK3PID.h"

#import "MXKTools.h"

#import "MXKTableViewCellWithButton.h"
#import "MXKTableViewCellWithTextFieldAndButton.h"
#import "MXKTableViewCellWithLabelTextFieldAndButton.h"
#import "MXKTableViewCellWithTextView.h"
#import "MXKTableViewCellWithLabelAndSwitch.h"

#import "NSBundle+MatrixKit.h"

#import "MXKConstants.h"

#import "MXKSwiftHeader.h"

NSString* const kMXKAccountDetailsLinkedEmailCellId = @"kMXKAccountDetailsLinkedEmailCellId";

@interface MXKAccountDetailsViewController ()
{
    NSMutableArray *alertsArray;
    
    // User's profile
    MXMediaLoader *imageLoader;
    NSString *currentDisplayName;
    NSString *currentPictureURL;
    NSString *currentDownloadId;
    NSString *uploadedPictureURL;
    // Local changes
    BOOL isAvatarUpdated;
    BOOL isSavingInProgress;
    blockMXKAccountDetailsViewController_onReadyToLeave onReadyToLeaveHandler;
    
    // account user's profile observer
    id accountUserInfoObserver;

    // Dynamic rows in the Linked emails section
    NSInteger submittedEmailRowIndex;
    
    // Notifications
    // Dynamic rows in the Notifications section
    NSInteger enablePushNotifRowIndex;
    NSInteger enableInAppNotifRowIndex;
    
    UIImagePickerController *mediaPicker;
}

@end

@implementation MXKAccountDetailsViewController
@synthesize userPictureButton, userDisplayName, saveUserInfoButton;
@synthesize profileActivityIndicator, profileActivityIndicatorBgView;

#pragma mark - Class methods

+ (UINib *)nib
{
    return [UINib nibWithNibName:NSStringFromClass([MXKAccountDetailsViewController class])
                          bundle:[NSBundle bundleForClass:[MXKAccountDetailsViewController class]]];
}

+ (instancetype)accountDetailsViewController
{
    return [[[self class] alloc] initWithNibName:NSStringFromClass([MXKAccountDetailsViewController class])
                                          bundle:[NSBundle bundleForClass:[MXKAccountDetailsViewController class]]];
}

#pragma mark -

- (void)finalizeInit
{
    [super finalizeInit];
    
    alertsArray = [NSMutableArray array];
    
    isAvatarUpdated = NO;
    isSavingInProgress = NO;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    // Check whether the view controller has been pushed via storyboard
    if (!userPictureButton)
    {
        // Instantiate view controller objects
        [[[self class] nib] instantiateWithOwner:self options:nil];
    }
    
    self.userPictureButton.backgroundColor = [UIColor clearColor];
    [self updateUserPictureButton:self.picturePlaceholder];
    
    [userPictureButton.layer setCornerRadius:userPictureButton.frame.size.width / 2];
    userPictureButton.clipsToBounds = YES;
    
    [saveUserInfoButton setTitle:[VectorL10n accountSaveChanges] forState:UIControlStateNormal];
    [saveUserInfoButton setTitle:[VectorL10n accountSaveChanges] forState:UIControlStateHighlighted];
    
    // Force refresh
    self.mxAccount = _mxAccount;
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
    
    if (imageLoader)
    {
        [imageLoader cancel];
        imageLoader = nil;
    }
}

- (void)dealloc
{
    alertsArray = nil;
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAPNSStatusUpdate) name:kMXKAccountAPNSActivityDidChangeNotification object:nil];
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    
    [self stopProfileActivityIndicator];
    
    [[NSNotificationCenter defaultCenter] removeObserver:self name:kMXKAccountAPNSActivityDidChangeNotification object:nil];
}

#pragma mark - override

- (void)onMatrixSessionChange
{
    [super onMatrixSessionChange];
    
    if (self.mainSession.state != MXSessionStateRunning)
    {
        userPictureButton.enabled = NO;
        userDisplayName.enabled = NO;
    }
    else if (!isSavingInProgress)
    {
        userPictureButton.enabled = YES;
        userDisplayName.enabled = YES;
    }
}

#pragma mark -

- (void)setMxAccount:(MXKAccount *)account
{
    // Remove observer and existing data
    [self reset];
    
    _mxAccount = account;
    
    if (account)
    {
        // Report matrix account session
        [self addMatrixSession:account.mxSession];
        
        // Set current user's information and add observers
        [self updateUserPicture:_mxAccount.userAvatarUrl force:YES];
        currentDisplayName = _mxAccount.userDisplayName;
        self.userDisplayName.text = currentDisplayName;
        [self updateSaveUserInfoButtonStatus];

        // Load linked emails
        [self loadLinkedEmails];

        // Add observer on user's information
        accountUserInfoObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kMXKAccountUserInfoDidChangeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
            // Ignore any refresh when saving is in progress
            if (self->isSavingInProgress)
            {
                return;
            }
            
            NSString *accountUserId = notif.object;
            
            if ([accountUserId isEqualToString:self->_mxAccount.mxCredentials.userId])
            {   
                // Update displayName
                if (![self->currentDisplayName isEqualToString:self->_mxAccount.userDisplayName])
                {
                    self->currentDisplayName = self->_mxAccount.userDisplayName;
                    self.userDisplayName.text = self->_mxAccount.userDisplayName;
                }
                // Update user's avatar
                [self updateUserPicture:self->_mxAccount.userAvatarUrl force:NO];
                
                // Update button management
                [self updateSaveUserInfoButtonStatus];
                
                // Display user's presence
                UIColor *presenceColor = [MXKAccount presenceColor:self->_mxAccount.userPresence];
                if (presenceColor)
                {
                    self->userPictureButton.layer.borderWidth = 2;
                    self->userPictureButton.layer.borderColor = presenceColor.CGColor;
                }
                else
                {
                    self->userPictureButton.layer.borderWidth = 0;
                }
            }
        }];
    }
    
    [self.tableView reloadData];
}

- (UIImage*)picturePlaceholder
{
    return [NSBundle mxk_imageFromMXKAssetsBundleWithName:@"default-profile"];
}

- (BOOL)shouldLeave:(blockMXKAccountDetailsViewController_onReadyToLeave)handler
{
    // Check whether some local changes have not been saved
    if (saveUserInfoButton.enabled)
    {
        dispatch_async(dispatch_get_main_queue(), ^{
            
            UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:[VectorL10n messageUnsavedChanges] preferredStyle:UIAlertControllerStyleAlert];
            
            [self->alertsArray addObject:alert];
            [alert addAction:[UIAlertAction actionWithTitle:[VectorL10n discard]
                                                      style:UIAlertActionStyleDefault
                                                    handler:^(UIAlertAction * action) {
                                                        
                                                        [self->alertsArray removeObject:alert];
                                                        
                                                        // Discard changes
                                                        self.userDisplayName.text = self->currentDisplayName;
                                                        [self updateUserPicture:self->_mxAccount.userAvatarUrl force:YES];
                                                        
                                                        // Ready to leave
                                                        if (handler)
                                                        {
                                                            handler();
                                                        }
                                                        
                                                    }]];
            
            [alert addAction:[UIAlertAction actionWithTitle:[VectorL10n save]
                                                      style:UIAlertActionStyleDefault
                                                    handler:^(UIAlertAction * action) {
                                                        
                                                        [self->alertsArray removeObject:alert];
                                                        
                                                        // Start saving (Report handler to leave at the end).
                                                        self->onReadyToLeaveHandler = handler;
                                                        [self saveUserInfo];
                                                        
                                                    }]];
            
            [self presentViewController:alert animated:YES completion:nil];
        });
        
        return NO;
    }
    else if (isSavingInProgress)
    {
        // Report handler to leave at the end of saving
        onReadyToLeaveHandler = handler;
        return NO;
    }
    return YES;
}

#pragma mark - Internal methods

- (void)startProfileActivityIndicator
{
    if (profileActivityIndicatorBgView.hidden)
    {
        profileActivityIndicatorBgView.hidden = NO;
        [profileActivityIndicator startAnimating];
    }
    userPictureButton.enabled = NO;
    userDisplayName.enabled = NO;
    saveUserInfoButton.enabled = NO;
}

- (void)stopProfileActivityIndicator
{
    if (!isSavingInProgress)
    {
        if (!profileActivityIndicatorBgView.hidden)
        {
            profileActivityIndicatorBgView.hidden = YES;
            [profileActivityIndicator stopAnimating];
        }
        userPictureButton.enabled = YES;
        userDisplayName.enabled = YES;
        [self updateSaveUserInfoButtonStatus];
    }
}

- (void)reset
{
    [self dismissMediaPicker];
    
    // Remove observers
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    
    // Cancel picture loader (if any)
    if (imageLoader)
    {
        [imageLoader cancel];
        imageLoader = nil;
    }
    
    // Cancel potential alerts
    for (UIAlertController *alert in alertsArray)
    {
        [alert dismissViewControllerAnimated:NO completion:nil];
    }
    
    // Remove listener
    if (accountUserInfoObserver)
    {
        [[NSNotificationCenter defaultCenter] removeObserver:accountUserInfoObserver];
        accountUserInfoObserver = nil;
    }
    
    currentPictureURL = nil;
    currentDownloadId = nil;
    uploadedPictureURL = nil;
    isAvatarUpdated = NO;
    [self updateUserPictureButton:self.picturePlaceholder];
    
    currentDisplayName = nil;
    self.userDisplayName.text = nil;
    
    saveUserInfoButton.enabled = NO;
    
    submittedEmail = nil;
    emailSubmitButton = nil;
    emailTextField = nil;
    
    [self removeMatrixSession:self.mainSession];
    
    logoutButton = nil;
    
    onReadyToLeaveHandler = nil;
}

- (void)destroy
{
    if (isSavingInProgress)
    {
        __weak typeof(self) weakSelf = self;
        onReadyToLeaveHandler = ^()
        {
            __strong __typeof(weakSelf)strongSelf = weakSelf;
            [strongSelf destroy];
        };
    }
    else
    {
        // Reset account to dispose all resources (Discard here potentials changes)
        self.mxAccount = nil;
        
        if (imageLoader)
        {
            [imageLoader cancel];
            imageLoader = nil;
        }
        
        // Remove listener
        if (accountUserInfoObserver)
        {
            [[NSNotificationCenter defaultCenter] removeObserver:accountUserInfoObserver];
            accountUserInfoObserver = nil;
        }
        
        [super destroy];
    }
}

- (void)saveUserInfo
{
    [self startProfileActivityIndicator];
    isSavingInProgress = YES;
    
    // Check whether the display name has been changed
    NSString *displayname = self.userDisplayName.text;
    if ((displayname.length || currentDisplayName.length) && [displayname isEqualToString:currentDisplayName] == NO)
    {
        // Save display name
        __weak typeof(self) weakSelf = self;
        
        [_mxAccount setUserDisplayName:displayname success:^{
            
            if (weakSelf)
            {
                // Update the current displayname
                typeof(self) self = weakSelf;
                self->currentDisplayName = displayname;
                
                // Go to the next change saving step
                [self saveUserInfo];
            }
            
        } failure:^(NSError *error) {
            
            MXLogDebug(@"[MXKAccountDetailsVC] Failed to set displayName");
            if (weakSelf)
            {
                typeof(self) self = weakSelf;
                
                // Alert user
                NSString *title = [error.userInfo valueForKey:NSLocalizedFailureReasonErrorKey];
                if (!title)
                {
                    title = [VectorL10n accountErrorDisplayNameChangeFailed];
                }
                NSString *msg = [error.userInfo valueForKey:NSLocalizedDescriptionKey];
                
                UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:msg preferredStyle:UIAlertControllerStyleAlert];
                
                [self->alertsArray addObject:alert];
                
                [alert addAction:[UIAlertAction actionWithTitle:[VectorL10n abort]
                                                          style:UIAlertActionStyleDefault
                                                        handler:^(UIAlertAction * action) {
                                                            
                                                            [self->alertsArray removeObject:alert];
                                                            // Discard changes
                                                            self.userDisplayName.text = self->currentDisplayName;
                                                            [self updateUserPicture:self.mxAccount.userAvatarUrl force:YES];
                                                            // Loop to end saving
                                                            [self saveUserInfo];
                                                            
                                                        }]];
                
                [alert addAction:[UIAlertAction actionWithTitle:[VectorL10n retry]
                                                          style:UIAlertActionStyleDefault
                                                        handler:^(UIAlertAction * action) {
                                                            
                                                            [self->alertsArray removeObject:alert];
                                                            // Loop to retry saving
                                                            [self saveUserInfo];
                                                            
                                                        }]];
                
                
                [self presentViewController:alert animated:YES completion:nil];
            }
            
         }];
        
        return;
    }
    
    // Check whether avatar has been updated
    if (isAvatarUpdated)
    {
        if (uploadedPictureURL == nil)
        {
            // Retrieve the current picture and make sure its orientation is up
            UIImage *updatedPicture = [MXKTools forceImageOrientationUp:[self.userPictureButton imageForState:UIControlStateNormal]];
            
            MXWeakify(self);
            
            // Upload picture
            MXMediaLoader *uploader = [MXMediaManager prepareUploaderWithMatrixSession:self.mainSession initialRange:0 andRange:1.0];
            [uploader uploadData:UIImageJPEGRepresentation(updatedPicture, 0.5) filename:nil mimeType:@"image/jpeg" success:^(NSString *url)
             {
                 MXStrongifyAndReturnIfNil(self);
                 
                 // Store uploaded picture url and trigger picture saving
                 self->uploadedPictureURL = url;
                 [self saveUserInfo];
             } failure:^(NSError *error)
             {
                 MXLogDebug(@"[MXKAccountDetailsVC] Failed to upload image");
                 MXStrongifyAndReturnIfNil(self);
                 [self handleErrorDuringPictureSaving:error];
             }];
            
        }
        else
        {
            MXWeakify(self);
            
            [_mxAccount setUserAvatarUrl:uploadedPictureURL
                                 success:^{
                                     
                                     // uploadedPictureURL becomes the user's picture
                                     MXStrongifyAndReturnIfNil(self);
                                     
                                     [self updateUserPicture:self->uploadedPictureURL force:YES];
                                     // Loop to end saving
                                     [self saveUserInfo];
                                     
                                 }
                                 failure:^(NSError *error) {
                                     MXLogDebug(@"[MXKAccountDetailsVC] Failed to set avatar url");
                                     MXStrongifyAndReturnIfNil(self);
                                     [self handleErrorDuringPictureSaving:error];
                                 }];
        }
        
        return;
    }
    
    // Backup is complete
    isSavingInProgress = NO;
    [self stopProfileActivityIndicator];
    
    // Ready to leave
    if (onReadyToLeaveHandler)
    {
        onReadyToLeaveHandler();
        onReadyToLeaveHandler = nil;
    }
}

- (void)handleErrorDuringPictureSaving:(NSError*)error
{
    NSString *title = [error.userInfo valueForKey:NSLocalizedFailureReasonErrorKey];
    if (!title)
    {
        title = [VectorL10n accountErrorPictureChangeFailed];
    }
    NSString *msg = [error.userInfo valueForKey:NSLocalizedDescriptionKey];
    
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:msg preferredStyle:UIAlertControllerStyleAlert];
    
    [alertsArray addObject:alert];
    [alert addAction:[UIAlertAction actionWithTitle:[VectorL10n abort]
                                              style:UIAlertActionStyleDefault
                                            handler:^(UIAlertAction * action) {
                                                
                                                [self->alertsArray removeObject:alert];
                                                
                                                // Remove change
                                                self.userDisplayName.text = self->currentDisplayName;
                                                [self updateUserPicture:self->_mxAccount.userAvatarUrl force:YES];
                                                // Loop to end saving
                                                [self saveUserInfo];
                                                
                                            }]];
    
    [alert addAction:[UIAlertAction actionWithTitle:[VectorL10n retry]
                                              style:UIAlertActionStyleDefault
                                            handler:^(UIAlertAction * action) {
                                                
                                                [self->alertsArray removeObject:alert];
                                                
                                                // Loop to retry saving
                                                [self saveUserInfo];
                                                
                                            }]];
    
    [self presentViewController:alert animated:YES completion:nil];
}

- (void)updateUserPicture:(NSString *)avatar_url force:(BOOL)force
{
    if (force || currentPictureURL == nil || [currentPictureURL isEqualToString:avatar_url] == NO)
    {
        // Remove any pending observers
        [[NSNotificationCenter defaultCenter] removeObserver:self];
        // Cancel previous loader (if any)
        if (imageLoader)
        {
            [imageLoader cancel];
            imageLoader = nil;
        }
        // Cancel any local change
        isAvatarUpdated = NO;
        uploadedPictureURL = nil;
        
        currentPictureURL = [avatar_url isEqual:[NSNull null]] ? nil : avatar_url;
        
        // Check whether this url is valid
        currentDownloadId = [MXMediaManager thumbnailDownloadIdForMatrixContentURI:currentPictureURL
                                                                          inFolder:kMXMediaManagerAvatarThumbnailFolder
                                                                     toFitViewSize:self.userPictureButton.frame.size
                                                                        withMethod:MXThumbnailingMethodCrop];
        if (!currentDownloadId)
        {
            // Set the placeholder in case of invalid Matrix Content URI.
            [self updateUserPictureButton:self.picturePlaceholder];
        }
        else
        {
            // Check whether the image download is in progress
            id loader = [MXMediaManager existingDownloaderWithIdentifier:currentDownloadId];
            if (loader)
            {
                // Observe this loader
                [[NSNotificationCenter defaultCenter] addObserver:self
                                                         selector:@selector(onMediaLoaderStateChange:)
                                                             name:kMXMediaLoaderStateDidChangeNotification
                                                           object:loader];
            }
            else
            {
                NSString *cacheFilePath = [MXMediaManager thumbnailCachePathForMatrixContentURI:currentPictureURL
                                                                                        andType:nil
                                                                                       inFolder:kMXMediaManagerAvatarThumbnailFolder
                                                                                  toFitViewSize:self.userPictureButton.frame.size
                                                                                     withMethod:MXThumbnailingMethodCrop];
                // Retrieve the image from cache
                UIImage* image = [MXMediaManager loadPictureFromFilePath:cacheFilePath];
                if (image)
                {
                    [self updateUserPictureButton:image];
                }
                else
                {
                    // Download the image, by adding download observer
                    [[NSNotificationCenter defaultCenter] addObserver:self
                                                             selector:@selector(onMediaLoaderStateChange:)
                                                                 name:kMXMediaLoaderStateDidChangeNotification
                                                               object:nil];
                    imageLoader = [self.mainSession.mediaManager downloadThumbnailFromMatrixContentURI:currentPictureURL
                                                                                              withType:nil
                                                                                              inFolder:kMXMediaManagerAvatarThumbnailFolder
                                                                                         toFitViewSize:self.userPictureButton.frame.size
                                                                                            withMethod:MXThumbnailingMethodCrop
                                                                                               success:nil
                                                                                               failure:nil];
                }
            }
        }
    }
}

- (void)updateUserPictureButton:(UIImage*)image
{
    [self.userPictureButton setImage:image forState:UIControlStateNormal];
    [self.userPictureButton setImage:image forState:UIControlStateHighlighted];
    [self.userPictureButton setImage:image forState:UIControlStateDisabled];
}

- (void)updateSaveUserInfoButtonStatus
{
    // Check whether display name has been changed
    NSString *displayname = self.userDisplayName.text;
    BOOL isDisplayNameUpdated = ((displayname.length || currentDisplayName.length) && [displayname isEqualToString:currentDisplayName] == NO);
    
    saveUserInfoButton.enabled = (isDisplayNameUpdated || isAvatarUpdated) && !isSavingInProgress;
}

- (void)onMediaLoaderStateChange:(NSNotification *)notif
{
    MXMediaLoader *loader = (MXMediaLoader*)notif.object;
    if ([loader.downloadId isEqualToString:currentDownloadId])
    {
        // update the image
        switch (loader.state) {
            case MXMediaLoaderStateDownloadCompleted:
            {
                UIImage *image = [MXMediaManager loadPictureFromFilePath:loader.downloadOutputFilePath];
                if (image == nil)
                {
                    image = self.picturePlaceholder;
                }
                [self updateUserPictureButton:image];
                // remove the observers
                [[NSNotificationCenter defaultCenter] removeObserver:self];
                imageLoader = nil;
                break;
            }
            case MXMediaLoaderStateDownloadFailed:
            case MXMediaLoaderStateCancelled:
                [self updateUserPictureButton:self.picturePlaceholder];
                // remove the observers
                [[NSNotificationCenter defaultCenter] removeObserver:self];
                imageLoader = nil;
                // Reset picture URL in order to try next time
                currentPictureURL = nil;
                break;
            default:
                break;
        }
    }
}

- (void)onAPNSStatusUpdate
{
    // Force table reload to update notifications section
    apnsNotificationsSwitch = nil;
    
    [self.tableView reloadData];
}

- (void)dismissMediaPicker
{
    if (mediaPicker)
    {
        [self dismissViewControllerAnimated:NO completion:nil];
        mediaPicker.delegate = nil;
        mediaPicker = nil;
    }
}

- (void)showValidationEmailDialogWithMessage:(NSString*)message
{
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:[VectorL10n accountEmailValidationTitle] message:message preferredStyle:UIAlertControllerStyleAlert];
    
    [alertsArray addObject:alert];
    [alert addAction:[UIAlertAction actionWithTitle:[VectorL10n abort]
                                              style:UIAlertActionStyleDefault
                                            handler:^(UIAlertAction * action) {
                                                
                                                [self->alertsArray removeObject:alert];
                                                
                                                self->emailSubmitButton.enabled = YES;
                                                
                                            }]];
    
    [alert addAction:[UIAlertAction actionWithTitle:[VectorL10n continue]
                                              style:UIAlertActionStyleDefault
                                            handler:^(UIAlertAction * action) {
                                                
                                                [self->alertsArray removeObject:alert];
                                                
                                                __weak typeof(self) weakSelf = self;
                                                
                                                // We do not bind anymore emails when registering, so let's do the same here
                                                [self->submittedEmail add3PIDToUser:NO success:^{
                                                    
                                                    if (weakSelf)
                                                    {
                                                        typeof(self) self = weakSelf;
                                                        
                                                        // Release pending email and refresh table to remove related cell
                                                        self->emailTextField.text = nil;
                                                        self->submittedEmail = nil;
                                                        
                                                        // Update linked emails
                                                        [self loadLinkedEmails];
                                                    }
                                                    
                                                } failure:^(NSError *error) {
                                                    
                                                    if (weakSelf)
                                                    {
                                                        typeof(self) self = weakSelf;
                                                        
                                                        MXLogDebug(@"[MXKAccountDetailsVC] Failed to bind email");
                                                        
                                                        // Display the same popup again if the error is M_THREEPID_AUTH_FAILED
                                                        MXError *mxError = [[MXError alloc] initWithNSError:error];
                                                        if (mxError && [mxError.errcode isEqualToString:kMXErrCodeStringThreePIDAuthFailed])
                                                        {
                                                            [self showValidationEmailDialogWithMessage:[VectorL10n accountEmailValidationError]];
                                                        }
                                                        else
                                                        {
                                                            // Notify MatrixKit user
                                                            NSString *myUserId = self.mxAccount.mxCredentials.userId;
                                                            [[NSNotificationCenter defaultCenter] postNotificationName:kMXKErrorNotification object:error userInfo:myUserId ? @{kMXKErrorUserIdKey: myUserId} : nil];
                                                        }
                                                        
                                                        // Release the pending email (even if it is Authenticated)
                                                        [self.tableView reloadData];
                                                    }
                                                    
                                                }];
                                                
                                            }]];
    
    [self presentViewController:alert animated:YES completion:nil];
}

- (void)loadLinkedEmails
{
    // Refresh the account 3PIDs list
    [_mxAccount load3PIDs:^{

        [self.tableView reloadData];

    } failure:^(NSError *error) {
        // Display the data that has been loaded last time
        [self.tableView reloadData];
    }];
}

#pragma mark - Actions

- (IBAction)onButtonPressed:(id)sender
{
    [self dismissKeyboard];

    if (sender == saveUserInfoButton)
    {
        [self saveUserInfo];
    }
    else if (sender == userPictureButton)
    {
        // Open picture gallery
        mediaPicker = [[UIImagePickerController alloc] init];
        mediaPicker.delegate = self;
        mediaPicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
        mediaPicker.allowsEditing = NO;
        [self presentViewController:mediaPicker animated:YES completion:nil];
    }
    else if (sender == logoutButton)
    {
        [[MXKAccountManager sharedManager] removeAccount:_mxAccount completion:nil];
        self.mxAccount = nil;
    }
    else if (sender == emailSubmitButton)
    {
        // Email check
        if (![MXTools isEmailAddress:emailTextField.text])
        {
            UIAlertController *alert = [UIAlertController alertControllerWithTitle:[VectorL10n accountErrorEmailWrongTitle] message:[VectorL10n accountErrorEmailWrongDescription] preferredStyle:UIAlertControllerStyleAlert];
            
            [alertsArray addObject:alert];
            [alert addAction:[UIAlertAction actionWithTitle:[VectorL10n ok]
                                                      style:UIAlertActionStyleDefault
                                                    handler:^(UIAlertAction * action) {
                                                        
                                                        [self->alertsArray removeObject:alert];
                                                        
                                                    }]];
            
            [self presentViewController:alert animated:YES completion:nil];

            return;
        }
        
        if (!submittedEmail || ![submittedEmail.address isEqualToString:emailTextField.text])
        {
            submittedEmail = [[MXK3PID alloc] initWithMedium:kMX3PIDMediumEmail andAddress:emailTextField.text];
        }
        
        emailSubmitButton.enabled = NO;
        __weak typeof(self) weakSelf = self;

        [submittedEmail requestValidationTokenWithMatrixRestClient:self.mainSession.matrixRestClient isDuringRegistration:NO nextLink:nil success:^{

            if (weakSelf)
            {
                typeof(self) self = weakSelf;
                [self showValidationEmailDialogWithMessage:[VectorL10n accountEmailValidationMessage]];
            }

        } failure:^(NSError *error) {

            MXLogDebug(@"[MXKAccountDetailsVC] Failed to request email token");
            if (weakSelf)
            {
                typeof(self) self = weakSelf;
                // Notify MatrixKit user
                NSString *myUserId = self.mxAccount.mxCredentials.userId;
                [[NSNotificationCenter defaultCenter] postNotificationName:kMXKErrorNotification object:error userInfo:myUserId ? @{kMXKErrorUserIdKey: myUserId} : nil];
                
                self->emailSubmitButton.enabled = YES;
            }

        }];
    }
    else if (sender == apnsNotificationsSwitch)
    {
        [_mxAccount enablePushNotifications:apnsNotificationsSwitch.on success:nil failure:nil];
        apnsNotificationsSwitch.enabled = NO;
    }
    else if (sender == inAppNotificationsSwitch)
    {
        _mxAccount.enableInAppNotifications = inAppNotificationsSwitch.on;
        [self.tableView reloadData];
    }
}

#pragma mark - keyboard

- (void)dismissKeyboard
{
    if ([userDisplayName isFirstResponder])
    {
        // Hide the keyboard
        [userDisplayName resignFirstResponder];
        [self updateSaveUserInfoButtonStatus];
    }
    else if ([emailTextField isFirstResponder])
    {
        [emailTextField resignFirstResponder];
    }
}

#pragma mark - UITextField delegate

- (BOOL)textFieldShouldReturn:(UITextField*)textField
{
    // "Done" key has been pressed
    [self dismissKeyboard];
    return YES;
}

- (IBAction)textFieldEditingChanged:(id)sender
{
    if (sender == userDisplayName)
    {
        [self updateSaveUserInfoButtonStatus];
    }
}

#pragma mark - UITableView data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    NSInteger count = 0;
    
    linkedEmailsSection = notificationsSection = configurationSection = -1;
    
    if (!_mxAccount.disabled)
    {
        linkedEmailsSection = count ++;
        notificationsSection = count ++;
    }
    
    configurationSection = count ++;
    
    return count;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    NSInteger count = 0;
    if (section == linkedEmailsSection)
    {
        count = _mxAccount.linkedEmails.count;
        submittedEmailRowIndex = count++;
    }
    else if (section == notificationsSection)
    {
        enableInAppNotifRowIndex = enablePushNotifRowIndex = -1;
        
        if ([MXKAccountManager sharedManager].isAPNSAvailable) {
            enablePushNotifRowIndex = count++;
        }
        enableInAppNotifRowIndex = count++;
    }
    else if (section == configurationSection)
    {
        count = 2;
    }
    
    return count;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.section == configurationSection)
    {
        if (indexPath.row == 0)
        {
            UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, MAXFLOAT)];
            textView.font = [UIFont systemFontOfSize:14];
            textView.text = [NSString stringWithFormat:@"%@\n%@\n%@", [VectorL10n settingsConfigHomeServer:_mxAccount.mxCredentials.homeServer], [VectorL10n settingsConfigIdentityServer:_mxAccount.identityServerURL], [VectorL10n settingsConfigUserId:_mxAccount.mxCredentials.userId]];
            
            CGSize contentSize = [textView sizeThatFits:textView.frame.size];
            return contentSize.height + 1;
        }
    }
    
    return 44;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = nil;
    
    if (indexPath.section == linkedEmailsSection)
    {
        if (indexPath.row < _mxAccount.linkedEmails.count)
        {
            cell = [tableView dequeueReusableCellWithIdentifier:kMXKAccountDetailsLinkedEmailCellId];
            if (!cell)
            {
                cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kMXKAccountDetailsLinkedEmailCellId];
            }
            
            cell.selectionStyle = UITableViewCellSelectionStyleNone;
            cell.textLabel.text = [_mxAccount.linkedEmails objectAtIndex:indexPath.row];
        }
        else if (indexPath.row == submittedEmailRowIndex)
        {
            // Report the current email value (if any)
            NSString *currentEmail = nil;
            if (emailTextField)
            {
                currentEmail = emailTextField.text;
            }
            
            MXKTableViewCellWithTextFieldAndButton *submittedEmailCell = [tableView dequeueReusableCellWithIdentifier:[MXKTableViewCellWithTextFieldAndButton defaultReuseIdentifier]];
            if (!submittedEmailCell)
            {
                submittedEmailCell = [[MXKTableViewCellWithTextFieldAndButton alloc] init];
            }
            
            submittedEmailCell.mxkTextField.text = currentEmail;
            submittedEmailCell.mxkTextField.keyboardType = UIKeyboardTypeEmailAddress;
            submittedEmailCell.mxkButton.enabled = (currentEmail.length != 0);
            [submittedEmailCell.mxkButton setTitle:[VectorL10n accountLinkEmail] forState:UIControlStateNormal];
            [submittedEmailCell.mxkButton setTitle:[VectorL10n accountLinkEmail] forState:UIControlStateHighlighted];
            [submittedEmailCell.mxkButton addTarget:self action:@selector(onButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
            
            emailSubmitButton = submittedEmailCell.mxkButton;
            emailTextField = submittedEmailCell.mxkTextField;

            cell = submittedEmailCell;
        }
    }
    else if (indexPath.section == notificationsSection)
    {
        MXKTableViewCellWithLabelAndSwitch *notificationsCell = [tableView dequeueReusableCellWithIdentifier:[MXKTableViewCellWithLabelAndSwitch defaultReuseIdentifier]];
        if (!notificationsCell)
        {
            notificationsCell = [[MXKTableViewCellWithLabelAndSwitch alloc] init];
        }
        else
        {
            // Force layout before reusing a cell (fix switch displayed outside the screen)
            [notificationsCell layoutIfNeeded];
        }
        
        [notificationsCell.mxkSwitch addTarget:self action:@selector(onButtonPressed:) forControlEvents:UIControlEventValueChanged];
        
        if (indexPath.row == enableInAppNotifRowIndex)
        {
            notificationsCell.mxkLabel.text = [VectorL10n settingsEnableInappNotifications];
            notificationsCell.mxkSwitch.on = _mxAccount.enableInAppNotifications;
            inAppNotificationsSwitch = notificationsCell.mxkSwitch;
        }
        else /* enablePushNotifRowIndex */
        {
            notificationsCell.mxkLabel.text = [VectorL10n settingsEnablePushNotifications];
            notificationsCell.mxkSwitch.on = _mxAccount.pushNotificationServiceIsActive;
            notificationsCell.mxkSwitch.enabled = YES;
            apnsNotificationsSwitch = notificationsCell.mxkSwitch;
        }
        
        cell = notificationsCell;
    }
    else if (indexPath.section == configurationSection)
    {
        if (indexPath.row == 0)
        {
            MXKTableViewCellWithTextView *configCell = [tableView dequeueReusableCellWithIdentifier:[MXKTableViewCellWithTextView defaultReuseIdentifier]];
            if (!configCell)
            {
                configCell = [[MXKTableViewCellWithTextView alloc] init];
            }
            
            configCell.mxkTextView.text = [NSString stringWithFormat:@"%@\n%@\n%@", [VectorL10n settingsConfigHomeServer:_mxAccount.mxCredentials.homeServer], [VectorL10n settingsConfigIdentityServer:_mxAccount.identityServerURL], [VectorL10n settingsConfigUserId:_mxAccount.mxCredentials.userId]];
            
            cell = configCell;
        }
        else
        {
            MXKTableViewCellWithButton *logoutBtnCell = [tableView dequeueReusableCellWithIdentifier:[MXKTableViewCellWithButton defaultReuseIdentifier]];
            if (!logoutBtnCell)
            {
                logoutBtnCell = [[MXKTableViewCellWithButton alloc] init];
            }
            [logoutBtnCell.mxkButton setTitle:[VectorL10n actionLogout] forState:UIControlStateNormal];
            [logoutBtnCell.mxkButton setTitle:[VectorL10n actionLogout] forState:UIControlStateHighlighted];
            [logoutBtnCell.mxkButton addTarget:self action:@selector(onButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
            
            logoutButton = logoutBtnCell.mxkButton;
            
            cell = logoutBtnCell;
        }
        
    }
    else
    {
        // Return a fake cell to prevent app from crashing.
        cell = [[UITableViewCell alloc] init];
    }
    
    return cell;
}

#pragma mark - UITableView delegate

- (CGFloat) tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    return 30;
}
- (CGFloat) tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
    return 1;
}

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    UIView *sectionHeader = [[UIView alloc] initWithFrame:[tableView rectForHeaderInSection:section]];
    sectionHeader.backgroundColor = [UIColor colorWithRed:0.9 green:0.9 blue:0.9 alpha:1.0];
    UILabel *sectionLabel = [[UILabel alloc] initWithFrame:CGRectMake(5, 5, sectionHeader.frame.size.width - 10, sectionHeader.frame.size.height - 10)];
    sectionLabel.font = [UIFont boldSystemFontOfSize:16];
    sectionLabel.backgroundColor = [UIColor clearColor];
    [sectionHeader addSubview:sectionLabel];
    
    if (section == linkedEmailsSection)
    {
        sectionLabel.text = [VectorL10n accountLinkedEmails];
    }
    else if (section == notificationsSection)
    {
        sectionLabel.text = [VectorL10n settingsTitleNotifications];
    }
    else if (section == configurationSection)
    {
        sectionLabel.text = [VectorL10n settingsTitleConfig];
    }
    
    return sectionHeader;
}

- (void)tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (self.tableView == aTableView)
    {
        [aTableView deselectRowAtIndexPath:indexPath animated:YES];
    }
}

# pragma mark - UIImagePickerControllerDelegate

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    UIImage *selectedImage = [info objectForKey:UIImagePickerControllerOriginalImage];
    if (selectedImage)
    {
        [self updateUserPictureButton:selectedImage];
        isAvatarUpdated = YES;
        saveUserInfoButton.enabled = YES;
    }
    [self dismissMediaPicker];
}

@end
